#pragma once

#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include "protocol.hpp"

class calClient
{
public:
    calClient(std::string ip, uint16_t port)
        : _sockfd(-1), _serverip(ip), _serverport(port)
    {
    }
    void initClient()
    {
        _sockfd = socket(AF_INET, SOCK_STREAM, 0);
        if (_sockfd < 0)
        {
            std::cerr << "socket error" << std::endl;
            exit(1);
        }
    }
    void run()
    {
        struct sockaddr_in peer;
        peer.sin_family = AF_INET;
        peer.sin_port = htons(_serverport);
        peer.sin_addr.s_addr = inet_addr(_serverip.c_str());

        int n = connect(_sockfd, (struct sockaddr*)&peer, sizeof(peer));
        if(n < 0)
        {
            std::cerr << "connect failed" << std::endl;
            exit(2);
        }

        std::string inbuffer;
        while(true)
        {
            std::cout << "Please Enter#";
            std::string message;
            getline(std::cin, message);

            Request rep = ParseLine(message);

            //将请求序列化
            std::string content;
            rep.serialize(&content);

            //封装成完整报文
            std::string send_string = enLength(content);

            send(_sockfd, send_string.c_str(), send_string.size(), 0);

            std::string package, resp_content;
            if (!recvPackage(_sockfd, inbuffer, &package))
                continue;;
            std::cout << 1 << std::endl;

            //解封
            if (!deLength(package, &resp_content))
                continue;
            //反序列化
            Response resp;
            resp.deserialize(resp_content);
            std::cout << "exitcode: " << resp.exitcode << std::endl; 
            std::cout << "result: " << resp.result << std::endl; 

        }
    }

    Request ParseLine(const std::string& line)
    {
        int status = 0;
        int i = 0;

        std::string left,right;
        char op;

        while(i < line.size())
        {
            //状态机
            switch(status)
            {
                case 0:
                if(!isdigit(line[i]))status = 1;
                else left.push_back(line[i++]);
                break;

                case 1:
                op = line[i++];
                status = 2;
                break;

                case 2:
                right.push_back(line[i++]);
                break;
            }
        }

        return Request(std::stoi(left), op, std::stoi(right));
    }

    ~calClient()
    {
    }

private:
    int _sockfd;
    std::string _serverip;
    uint16_t _serverport;
};
